/*******************************************************************************
 * This file is part of blueprint4j www.blueprint4j.org.
 * 
 *     blueprint4j is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Lesser General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 * 
 *     blueprint4j is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU Lesser General Public License for more details.
 * 
 *     You should have received a copy of the GNU Lesser General Public License
 *     along with blueprint4j. If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/
package blueprint4j.apps;

import java.awt.BorderLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;

import blueprint4j.gui.db.Editor;

public class ApplicationLayoutBasic implements ApplicationLayout {
	private boolean isBuilt=false;
	private JPanel main = new JPanel(new BorderLayout());
	private JMenuBar menuBar = new JMenuBar();
	private String currentItem = null;
	private List<String> menuItemsList = new ArrayList<String>();
	private Map<String, Editor> menuHashMap = new HashMap<String, Editor>();
	private Map<String, ApplicationAction> menuActionHashMap = new HashMap<String, ApplicationAction>();
	private Map<String, Image> iconActionHashMap = new HashMap<String, Image>();
	private Map<String, KeyStroke> keyActionHashMap = new HashMap<String, KeyStroke>();

	public ApplicationLayoutBasic(String defaultItem) {
		this.currentItem = defaultItem;
	}

	@Override
	public void addInterface(String menu, Editor component) {
		menuItemsList.add(menu);
		menuHashMap.put(menu, component);
		isBuilt=false;
	}

	@Override
	public void addInterface(String menu, KeyStroke ks,Image icon, Editor component) {
		// TODO add this icon to the menu
		menuItemsList.add(menu);
		menuHashMap.put(menu, component);
		iconActionHashMap.put(menu, icon);
		keyActionHashMap.put(menu, ks);
		isBuilt=false;
	}

	@Override
	public void addInterface(String menu, KeyStroke ks,Editor component) {
		// TODO add this icon to the menu
		menuItemsList.add(menu);
		menuHashMap.put(menu, component);
		keyActionHashMap.put(menu, ks);
		isBuilt=false;
	}

	@Override
	public void addInterface(String menu, Image icon, Editor component) {
		// TODO add this icon to the menu
		menuItemsList.add(menu);
		menuHashMap.put(menu, component);
		iconActionHashMap.put(menu, icon);
		isBuilt=false;
	}

	@Override
	public void addAction(String menu, ApplicationAction action) {
		menuItemsList.add(menu);
		menuActionHashMap.put(menu, action);
		isBuilt=false;
	}

	@Override
	public void addAction(String menu, Image icon, ApplicationAction action) {
		// TODO add this icon to the menu
		menuItemsList.add(menu);
		menuActionHashMap.put(menu, action);
		isBuilt=false;
	}

	@Override
	public void addAction(String menu, KeyStroke ks,Image icon, ApplicationAction action) {
		// TODO add this icon to the menu
		menuItemsList.add(menu);
		menuActionHashMap.put(menu, action);
		iconActionHashMap.put(menu, icon);
		keyActionHashMap.put(menu, ks);
		isBuilt=false;
	}

	@Override
	public void addAction(String menu, KeyStroke ks,ApplicationAction action) {
		// TODO add this icon to the menu
		menuItemsList.add(menu);
		menuActionHashMap.put(menu, action);
		keyActionHashMap.put(menu, ks);
		isBuilt=false;
	}

	@Override
	public JComponent getComponent(JFrame frame) {
		if (!isBuilt) {
			build();
		}
		frame.setJMenuBar(menuBar);
		return main;
	}

	@Override
	public void selectInterface(final String menu) {
		SwingUtilities.invokeLater(new Runnable() {

			@Override
			public void run() {
				Editor editor;
				if (menuHashMap.containsKey(currentItem)) {
					editor=menuHashMap.get(currentItem);
					if (!editor.getEntityEditor().save()){
						return;
					}
					main.remove(editor.getComponent());
				}
				
				editor=menuHashMap.get(menu);
				editor.activated();
				main.add(editor.getComponent());
				currentItem = menu;
			}

		});
	}

	private void build() {
		isBuilt=true;
		SwingUtilities.invokeLater(new Runnable() {

			@Override
			public void run() {
				main.removeAll();

				Map<String, JMenu> menuMap = new HashMap<String, JMenu>();

				menuBar.removeAll();

				for (String menuPath : menuItemsList) {
					int lastSplit = menuPath.lastIndexOf(MENU_SPLIT_CHARACTER);
					String menuName;
					String item;
					if (lastSplit == -1) {
						menuName = "Default";
						item=menuPath;
					} else {
						menuName = menuPath.substring(0, lastSplit);
						item=menuPath.substring(lastSplit+MENU_SPLIT_CHARACTER.length());

					}

					JMenu menu = menuMap.get(menuName);
					if (menu == null) {

						String menuPathParts[]=menuName.split(MENU_SPLIT_REG);
						
						StringBuffer menuPathBuild=new StringBuffer();

						JMenu lastMenu = null;
						for (String nextPart:menuPathParts){
							menuPathBuild.append(menuPathBuild.length()>0?MENU_SPLIT_CHARACTER:"");
							menuPathBuild.append(nextPart);

							String menuSubPath=menuPathBuild.toString();
							if (!menuMap.containsKey(menuSubPath)){
								menu = new JMenu(nextPart);
								menuMap.put(menuSubPath, menu);
								if (lastMenu==null){
									menuBar.add(menu);
								}else{
									lastMenu.add(menu);
								}
								lastMenu=menu;
							}else{
								lastMenu=menuMap.get(menuSubPath);
							}
						}
					}
					JMenuItem menuItem;
					AbstractAction a;
					if (menuHashMap.containsKey(menuPath)){
						a=new ALBAction(menuPath, item);
 					}else {
 						a=new ApplicationActionWrapper(menuPath, item,menuActionHashMap.get(menuPath));
					}
					if (iconActionHashMap.containsKey(menuPath)){
						a.putValue(AbstractAction.SMALL_ICON, iconActionHashMap.get(menuPath));
					}
					if (keyActionHashMap.containsKey(menuPath)){
						a.putValue(AbstractAction.ACCELERATOR_KEY, keyActionHashMap.get(menuPath));
					}
					menuItem=new JMenuItem(a);

					menuItem.setEnabled(true);
					menu.add(menuItem);
					
					if (menuPath.equals(currentItem)) {
						main.add(menuHashMap.get(menuPath).getComponent(),BorderLayout.CENTER);
					}
				}
			}
		});
	}
	
	class ALBAction extends AbstractAction {
		private static final long serialVersionUID = 1L;

		public String menuPath;

		ALBAction(String menuPath, String name) {
			super(name);
			this.menuPath = menuPath;
		}

		public void actionPerformed(ActionEvent actionEvent) {
			selectInterface(menuPath);
		}
	}

	class ApplicationActionWrapper extends AbstractAction {
		private static final long serialVersionUID = 1L;

		public String menuPath;
		public ApplicationAction action;

		ApplicationActionWrapper(String menuPath, String name,ApplicationAction action) {
			super(name);
			this.menuPath = menuPath;
			this.action=action;
		}

		public void actionPerformed(ActionEvent actionEvent) {
			action.performAction();
		}
	}
	
}
